package hunterxhunter.greedisland.states;

import hunterxhunter.greedisland.GreedIslandGame;
import hunterxhunter.greedisland.data.AnimationSequence;
import hunterxhunter.greedisland.data.enums.Direction;
import hunterxhunter.greedisland.entities.menu.GameplayMenuEntity;
import hunterxhunter.greedisland.entities.sprite.AnimatedBodyEntity;
import hunterxhunter.greedisland.events.KeyPressedEvent;
import hunterxhunter.greedisland.events.KeyPressedReleasedUseOneReleaseActionEvent;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import framework.eea.StateBasedGame;
import framework.eea.entity.Entity;
import framework.eea.entity.EntityManager;
import framework.eea.event.Component;
import framework.eea.event.Event;
import framework.eea.exception.EEAException;
import framework.eea.gui.Graphics;
import framework.eea.gui.JFrameGameContainer;
import framework.eea.interfaces.Action;
import framework.eea.state.GameState;
import hunterxhunter.greedisland.data.map.LayerType;
import hunterxhunter.greedisland.data.map.Map;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.World;

/**
 *
 * @author Markus Schr&ouml;der
 */
public class GameplayState extends GameState {

    //JBox2D
    private World world;

    //ENTITY
    private Entity stateEntity;
    
    //CONTROL
    private AnimatedBodyEntity controlEntity;
    private KeyPressedReleasedUseOneReleaseActionEvent moveControlEntityEvent;
    private Dimension translation;
    
    //MENU
    private GameplayMenuEntity menu;
    
    //MAP
    private Point mapOffset;
    
    public GameplayState() {
        stateEntity = new Entity("GameplayState");
        translation = new Dimension();
        
        mapOffset = new Point(
                -(Map.MAX_WIDTH * GreedIslandGame.getTileSize().width)/2, 
                -(Map.MAX_HEIGHT * GreedIslandGame.getTileSize().height)/2);
    }
    
    @Override
    public void init(JFrameGameContainer gc, final StateBasedGame sbg) throws EEAException {
        
        world = new World(new Vec2(0, 0));

        menu = new GameplayMenuEntity();
        
        //create entity
        controlEntity = new AnimatedBodyEntity("controlEntity", 
                BodyType.DYNAMIC, 
                new Point(0,0),
                new Dimension(16, 16),
                5, 1,
                world);
        
        controlEntity.setShowBorder(true);
        
        //add animation sequence
        controlEntity.getAnimations().put(Direction.DOWN.toAnimation(), new AnimationSequence("/greedisland/img/gon.png",
        new Rectangle(81,41,30,39), new Rectangle(81,82,30,39), new Rectangle(2,122,30,39), new Rectangle(81,122,30,39), new Rectangle(2,122,30,39)));
        //new Rectangle(81,41,30,39), new Rectangle(81,82,30,39), new Rectangle(81,122,30,39), new Rectangle(2,122,30,39)));
        controlEntity.getAnimations().put(Direction.LEFT.toAnimation(), new AnimationSequence("/greedisland/img/gon.png",
        new Rectangle(163,83,31,40), new Rectangle(163,124,31,40), new Rectangle(163,83,31,40), new Rectangle(163,164,31,40)));
        controlEntity.getAnimations().put(Direction.RIGHT.toAnimation(), new AnimationSequence("/greedisland/img/gon.png",
        new Rectangle(328,0,31,40), new Rectangle(328,41,31,40), new Rectangle(328,0,31,40), new Rectangle(328,81,31,40)));
        controlEntity.getAnimations().put(Direction.UP.toAnimation(), new AnimationSequence("/greedisland/img/gon.png",
        new Rectangle(4,162,29,38), new Rectangle(165,4,29,38), new Rectangle(4,162,29,38), new Rectangle(165,44,29,38)));
        
        
        //show image
        controlEntity.freeze(Direction.DOWN.toAnimation(), 0);
        
        
        EntityManager.getInstance().addEntity(ID, controlEntity);
        
        
        
        moveControlEntityEvent = new KeyPressedReleasedUseOneReleaseActionEvent(new int[] { 
            KeyEvent.VK_DOWN, KeyEvent.VK_UP, KeyEvent.VK_RIGHT, KeyEvent.VK_LEFT
        }, new Action[] { 
            new Action() {
                public void update(JFrameGameContainer gc, StateBasedGame sb, int delta, Component event) {
                    controlEntity.move(Direction.DOWN);
                }
            },
            new Action() {
                public void update(JFrameGameContainer gc, StateBasedGame sb, int delta, Component event) {
                    controlEntity.move(Direction.UP);
                }
            },
            new Action() {
                public void update(JFrameGameContainer gc, StateBasedGame sb, int delta, Component event) {
                    controlEntity.move(Direction.RIGHT);
                }
            },
            new Action() {
                public void update(JFrameGameContainer gc, StateBasedGame sb, int delta, Component event) {
                    controlEntity.move(Direction.LEFT);
                }
            }
        }, 
        new Action() {
            public void update(JFrameGameContainer gc, StateBasedGame sb, int delta, Component event) {
                controlEntity.stand();
            }
        });
        
        //"BOOK"
        Event bookEvent = new KeyPressedEvent(new Action() {
            public void update(JFrameGameContainer gc, StateBasedGame sb, int delta, Component event) {
                moveControlEntityEvent.setActive(!moveControlEntityEvent.isActive());
                menu.setVisible(!menu.isVisible());
                controlEntity.stand();
                controlEntity.showEmote("BOOK!", 1000);
            }
        }, KeyEvent.VK_B);
        
        //"GAIN"
        Event gainEvent = new KeyPressedEvent(new Action() {
            public void update(JFrameGameContainer gc, StateBasedGame sb, int delta, Component event) {
                controlEntity.showEmote("GAIN!", 1000);
            }
        }, KeyEvent.VK_G);
        
        //"SAVED"
        Event saveEvent = new KeyPressedEvent(new Action() {
            public void update(JFrameGameContainer gc, StateBasedGame sb, int delta, Component event) {
                //TODO save map
                ((GreedIslandGame)sb).saveMap();
                controlEntity.showEmote("SAVED", 1000);
            }
        }, KeyEvent.VK_S);
        
        //update map
        Event updateEvent = new KeyPressedEvent(new Action() {
            public void update(JFrameGameContainer gc, StateBasedGame sb, int delta, Component event) {
                ((GreedIslandGame)sbg).getMap().updateWorld(
                        getMapOffset().x, getMapOffset().y, 
                        GreedIslandGame.getTileSize().width, GreedIslandGame.getTileSize().height, world);
                controlEntity.showEmote("UPDATE", 1000);
            }
        }, KeyEvent.VK_U);
        
        stateEntity.addComponent(moveControlEntityEvent);
        stateEntity.addComponent(bookEvent);
        stateEntity.addComponent(gainEvent);
        stateEntity.addComponent(updateEvent);
        stateEntity.addComponent(saveEvent);
    }
    
    @Override
    public void enter(JFrameGameContainer gc, StateBasedGame sbg) throws EEAException {
        //load map
        ((GreedIslandGame)sbg).loadMap();
        //set control entity position
        //TODO
    }

    @Override
    public void render(JFrameGameContainer gc, StateBasedGame sbg, Graphics g) throws EEAException {
        
        //BACKGROUND BEGIN
        //g.clear(Color.green);
        //BACKGROUND END
        
        translation = g.centerEntity(controlEntity);
        
        //MAP BACKGROUND FOREGROUND BEGIN
        ((GreedIslandGame)sbg).getMap().render(
                getMapOffset().x, getMapOffset().y, 
                GreedIslandGame.getTileSize().width, GreedIslandGame.getTileSize().height, 
                new LayerType[] { LayerType.BACKGROUND, LayerType.FOREGROUND }, true, g);
        //MAP END
        
        //SPRITES BEGIN
        EntityManager.getInstance().renderEntities(gc, sbg, g);
        //SPRITES END
        
        //MAP ALWAYS ON TOP BEGIN
        ((GreedIslandGame)sbg).getMap().render(
                getMapOffset().x, getMapOffset().y, 
                GreedIslandGame.getTileSize().width, GreedIslandGame.getTileSize().height, 
                new LayerType[] { LayerType.ALWAYS_ON_TOP }, false, g);
        //MAP END
        
        
        //MENU BEGIN
        g.resetTranslation();
        menu.render(gc, sbg, g);
        //MENU END
    }
    
    @Override
    public void update(JFrameGameContainer gc, StateBasedGame sbg, int delta) throws EEAException {
        menu.update(gc, sbg, delta);
        stateEntity.update(gc, sbg, delta);
        EntityManager.getInstance().updateEntities(gc, sbg, delta);
        world.step(1/JFrameGameContainer.FPS, 5, 5);
    }
    
    
    
    
    
    /**
     * ID = 3
     */
    public static final int ID = 3;

    @Override
    public int getID() {
        return ID;
    }

    /**
     * @return the translation
     */
    public Dimension getTranslation() {
        return translation;
    }

    /**
     * @return the mapOffset
     */
    public Point getMapOffset() {
        return mapOffset;
    }
}
